#include "StdAfx.h"
#include "GlobalOperator.h"
#include "Parameter.h"
#include "ScheduleManager.h"
#include "MKadNode.h"

	
CGlobalOperator::CGlobalOperator(const NODE_INDEX nNodeIndex)
	: CNode(nNodeIndex) 
	, m_nDataPublishCount(0)
	, fout_data("result\\data_log.log")
	, fout_budget("result\\budget_log.log")
	, fout_node_search("result\\node_Search.log")
	, fout_data_search("result\\data_search.log")
	, fout_in_degree("result\\incoming_link.log")
	, fout_size("result\\network_size.log")
	, fout_drange("result\\Dyanmic_range_test_log.log")
	, fout_visit_ratio("result\\visit_ratio_log.log")
	, fout_data_ratio("result\\data_ratio_log.log")
	, fout_visit_ratio_drange("result\\visit_ratio_drange_log.log")
	, fout_data_ratio_drange("result\\data_ratio_drange_log.log")

{
	ifstream fin(DATA_PATH_NAME);
	if(fin)
	{
		printf("Loading data file ...\n");
		char buf[1024];
		while(fin.getline(buf,1024))
		{
			m_cDataImage.push_back(KEY(string(buf)));
		}
		printf("Load finished.\n");
	}
	else
	{
		printf("Can not load data file.");
		_getch();
		exit(0);
	}
	ifstream fin2(SEED_PATH_NAME);
	if(fin2)
	{
		printf("Loading Seed File ...\n");
		char buf[1024];
		char Number[256];
		while(fin2.getline(buf,1024))
		{
			fin2.getline(Number,256);
			m_cSeedImage.push_back(make_pair(KEY(string(buf)),(int)strtol(Number, NULL, 10)));
		}
		printf("Load finished.\n");
	}
	else
	{
		printf("Can not load seed file.");
		_getch();
		exit(0);
	}
	ifstream fin3(RANGE_SEED_PATH_NAME);
	if(fin3)
	{
		printf("Loading Seed File 2 ...\n");
		char buf[1024];
		char Number[256];
		while(fin3.getline(buf,1024))
		{
			m_cRangeSeedImage.push_back(make_pair(KEY(string(buf)),vector<int>(SEARCH_RANGE_STEP)));
			vector<int> &cRangeList = m_cRangeSeedImage.rbegin()->second;
			for(int i = 0;i<SEARCH_RANGE_STEP;i++)
			{
				fin3.getline(Number,256);
				cRangeList[i]=(int)strtol(Number, NULL, 10);
			}
		}
		printf("Load finished.\n");
	}
	else
	{
		printf("Can not load seed file.");
		_getch();
		exit(0);
	}
}

CGlobalOperator::~CGlobalOperator(void)
{
}
void CGlobalOperator::OnTimer(const TIMER_TYPE dwType)
{
	switch(dwType)
	{
		case TM_REPORT:
			{
				printf("At Time %u:\n",g_dwCurrentTime);
				OutputDebugInfo("At Time %u:\n",g_dwCurrentTime);

				printf("\tCurrent Network Size: %u.\n", g_pScheduler->GetNetworkSize());
				OutputDebugInfo("\tCurrent Network Size: %u.\n", g_pScheduler->GetNetworkSize());
				CCalculator  cData, cBudget,cInLink;
				map<NODE_INDEX,int> cIncomingLink;
				for(map<NODE_INDEX,CNode*>::iterator it = g_pScheduler->m_cOnlineNodeList.begin();it!=g_pScheduler->m_cOnlineNodeList.end();++it)
				{
					CMKadNode* pNode = (CMKadNode* )it->second;
					cData.Add(pNode->GetDataCount());
					cBudget.Add(pNode->GetValidBudgetItemCount());
					set<NODE_INDEX> cBgt;
					pNode->GetBudgetList(cBgt);
					for(set<NODE_INDEX> ::iterator it =cBgt.begin();it!=cBgt.end();++it)
					{
						map<NODE_INDEX,int>::iterator in_it = cIncomingLink.find(*it);
						if(in_it==cIncomingLink.end())
						{
							in_it = cIncomingLink.insert(make_pair(*it,0)).first;
						}
						in_it->second++;
					}
				}
				for(map<NODE_INDEX,int>::iterator it = cIncomingLink.begin();it!=cIncomingLink.end();++it)
				{
					cInLink.Add(it->second);
				}
				cData.Calculate();
				cBudget.Calculate();
				cInLink.Calculate();
				printf("\t Data Size: Mean: %.3lf, Max: %.0lf, Min: %.0lf, SDEV: %.3lf \n",cData.GetEven(),cData.GetMax(),cData.GetMin(),cData.GetSDev());
				OutputDebugInfo("\t Data Size:, Mean: %.3lf, Max: %.0lf, Min: %.0lf, SDEV: %.3lf \n",cData.GetEven(),cData.GetMax(),cData.GetMin(),cData.GetSDev());
				
				printf("\t Budget: Mean: %.3lf, Max: %.0lf, Min: %.0lf, SDEV: %.3lf \n",cBudget.GetEven(),cBudget.GetMax(),cBudget.GetMin(),cBudget.GetSDev());
				OutputDebugInfo("\t Outgoing Degree: Mean: %.3lf, Max: %.0lf, Min: %.0lf, SDEV: %.3lf \n",cBudget.GetEven(),cBudget.GetMax(),cBudget.GetMin(),cBudget.GetSDev());
				
				fout_size<<g_dwCurrentTime<<" "<<g_pScheduler->GetNetworkSize()<<endl;
				fout_data<<g_dwCurrentTime<<" "<<cData.GetEven()<<" "<<cData.GetMax()<<" "<<cData.GetMin()<<" "<<cData.GetSDev()<<endl;
				fout_budget<<g_dwCurrentTime<<" "<<cBudget.GetEven()<<" "<<cBudget.GetMax()<<" "<<cBudget.GetMin()<<" "<<cBudget.GetSDev()<<endl;
				fout_in_degree<<g_dwCurrentTime<<" "<<cInLink.GetEven()<<" "<<cInLink.GetMax()<<" "<<cInLink.GetMin()<<" "<<cInLink.GetSDev()<<endl;
			}
			break;
		case TM_SEARCH_NODE:
			{
				OnSearchNode();
			}
			break;
		case TM_SEARCH_DATA:
			{
				OnSearchData();
			}
			break;
		case TM_INSERT_DATA:
			{
				OnInsertData();
			}
			break;
		case TM_SEARCH_DATA_MULTIP_RANGE:
			{
				OnSearchDataMultipRange();
			}
			break;
		case TM_SNAPSHOT:
			{
				OnSnapShot();
			}
		default:
			{
				break;
			}
	};
	CNode::OnTimer(dwType);
	return ;
}

void CGlobalOperator::OnJoin(void)
{
	if(REPORT_ROUND>0)
	{
		this->AddTimer(TM_REPORT,rand_range(0,REPORT_ROUND),REPORT_ROUND);
	}
	if(SEARCH_NODE_ROUND>0)
	{
		this->AddTimer(TM_SEARCH_NODE,rand_range(0,SEARCH_NODE_ROUND),SEARCH_NODE_ROUND);
	}
	if(SNAPSHOT_ROUND>0)
	{
		this->AddTimer(TM_SNAPSHOT,SNAPSHOT_ROUND,SNAPSHOT_ROUND);
	}
	if(SEARCH_DATA_ROUND>0)
	{
		this->AddTimer(TM_SEARCH_DATA,DATA_SEARCH_START_TIME,SEARCH_DATA_ROUND);
	}
	if(DATA_INSERT_ROUND>0)
	{
		this->AddTimer(TM_INSERT_DATA,1,DATA_INSERT_ROUND);
	}
	if(MULTIP_RANGE_DATA_SEARCH_TIME>0)
	{
		this->AddAlarm(TM_SEARCH_DATA_MULTIP_RANGE,MULTIP_RANGE_DATA_SEARCH_TIME);
	}
	CNode::OnJoin();
	
}

void CGlobalOperator::OnLeave(void)
{
	CNode::OnLeave();
}
void CGlobalOperator::OnInsertData(void)
{
	if(g_pScheduler->GetNetworkSize()==0)
	{
		return;
	}
	for( int i = 0;i<DATA_INSERT_NUMBER&&m_nDataPublishCount<(int)m_cDataImage.size();i++)
	{
		CMKadNode *pNode = (CMKadNode*)g_pScheduler->GetRandomNode();
		pNode->Publish(m_cDataImage[m_nDataPublishCount],CValue());
		m_nDataPublishCount++;
	}
}

void CGlobalOperator::OnSearchNode(void)
{
	if(g_pScheduler->GetNetworkSize()==0)
	{
		return;
	}
	CCalculator cCal;
	int nDis =64;
	int nSuccess = 0;
	for(int i = 0;i<SAMPLING_NUMBER;i++)
	{
		CMKadNode *pFrom = (CMKadNode*)g_pScheduler->GetRandomNode();
		CMKadNode *pNode = (CMKadNode*)g_pScheduler->GetRandomNode();
		KEY dest = pNode->GetNodeID();
		int nRes = pFrom->FindRemoteNodeForTest(dest,QUERY_SEARCHDEPTH);
		if(nRes>0)
		{
			nSuccess++;
			cCal.Add(nRes);
		}
	}
	cCal.Calculate();
	fout_node_search<<GetCurTime()<<" "<<nSuccess<<" "<<cCal.GetEven()<<" "<<cCal.GetMax()<<" "<<cCal.GetMin()<<" "<<cCal.GetSDev()<<endl;

}

void CGlobalOperator::OnSearchData(void)
{
	if(g_pScheduler->GetNetworkSize()==0)
	{
		return;
	}
	else
	{
		vector<CCalculator> cCal(SEARCH_STEPS);
		vector<CCalculator> cCal2(SEARCH_STEPS);
		vector<CCalculator> cCal3(SEARCH_STEPS);
		for(int i = 0;i<SAMPLING_NUMBER;i++)
		{

			for(int j = 0;j<SEARCH_STEPS;j++)
			{	
				unsigned nPos = rand()%(m_cSeedImage.size());
				KEY &dest = m_cSeedImage[nPos].first;
				int nRealRes = m_cSeedImage[nPos].second;
				CMKadNode *pFrom = (CMKadNode*)g_pScheduler->GetRandomNode();
				vector<pair<KEY,CValue>>  cStorer;
				int nSearchDepth = QUERY_SEARCHDEPTH*(j+1)/SEARCH_STEPS;
				unsigned int  nAccessNode = 0,nAccessData=0;
				pFrom->FindRemoteData(dest,CLUSTER_RADIUS,nSearchDepth,nRealRes,cStorer,nAccessNode,nAccessData);
				cCal[j].Add((double)cStorer.size()*100/nRealRes);
				cCal2[j].Add((double)nAccessNode*100/g_pScheduler->GetNetworkSize());
				cCal3[j].Add((double)nAccessData*100/m_nDataPublishCount/PUBLISH_REDUNDANCE);
			}
		}	
		for(int i = 0;i<SEARCH_STEPS;i++)
		{
			cCal[i].Calculate();
			cCal2[i].Calculate();
			cCal3[i].Calculate();
			fout_data_search<<GetCurTime()<<" "<<QUERY_SEARCHDEPTH*(i+1)/SEARCH_STEPS<<" "<<cCal[i].GetEven()<<" "<<cCal[i].GetMax()<<" "<<cCal[i].GetMin()<<" "<<cCal[i].GetSDev()<<endl;
			fout_visit_ratio<<GetCurTime()<<" "<<QUERY_SEARCHDEPTH*(i+1)/SEARCH_STEPS<<" "<<cCal2[i].GetEven()<<" "<<cCal2[i].GetMax()<<" "<<cCal2[i].GetMin()<<" "<<cCal2[i].GetSDev()<<endl;
			fout_data_ratio<<GetCurTime()<<" "<<QUERY_SEARCHDEPTH*(i+1)/SEARCH_STEPS<<" "<<cCal3[i].GetEven()<<" "<<cCal3[i].GetMax()<<" "<<cCal3[i].GetMin()<<" "<<cCal3[i].GetSDev()<<endl;
		}
		
	}
}
void CGlobalOperator::OnSearchDataMultipRange()
{
	for(int depth =0;depth<SEARCH_STEPS;++depth)
	{
		int nSearchDepth = QUERY_SEARCHDEPTH*(depth+1)/SEARCH_STEPS;
					
		for(int radius = 0;radius<SEARCH_RANGE_STEP;radius++)
		{
			unsigned nPos = rand()%(m_cRangeSeedImage.size());
			KEY &dest = m_cRangeSeedImage[nPos].first;
			int nSearchRadius = D2I(MIN_SEARCH_RANGE+((float)(MAX_SEARCH_RANGE-MIN_SEARCH_RANGE))*radius/(SEARCH_RANGE_STEP-1));
			int nRealRes = m_cRangeSeedImage[nPos].second[radius];
			CCalculator cCal,cCal2,cCal3;
			for(int i = 0;i<SAMPLING_NUMBER;i++)
			{
				CMKadNode *pFrom = (CMKadNode*)g_pScheduler->GetRandomNode();
				vector<pair<KEY,CValue>>  cStorer;
				unsigned int  nAccessNode = 0,nAccessData = 0;
				pFrom->FindRemoteData(dest,nSearchRadius,nSearchDepth,nRealRes*3/2,cStorer,nAccessNode,nAccessData);
				cCal.Add(cStorer.size()*100/(double)nRealRes);
				cCal2.Add((double)nAccessNode*100/g_pScheduler->GetNetworkSize());
				cCal3.Add((double)nAccessData*100/m_nDataPublishCount/PUBLISH_REDUNDANCE);
			}
			cCal.Calculate();
			cCal2.Calculate();
			cCal3.Calculate();
			fout_drange<<nSearchRadius<<" "<<nSearchDepth<<" "<<cCal.GetEven()<<" "<<cCal.GetMax()<<" "<<cCal.GetMin()<<" "<<cCal.GetSDev()<<endl;
			fout_visit_ratio_drange<<nSearchRadius<<" "<<nSearchDepth<<" "<<cCal2.GetEven()<<" "<<cCal2.GetMax()<<" "<<cCal2.GetMin()<<" "<<cCal2.GetSDev()<<endl;
			fout_data_ratio_drange<<nSearchRadius<<" "<<nSearchDepth<<" "<<cCal3.GetEven()<<" "<<cCal3.GetMax()<<" "<<cCal3.GetMin()<<" "<<cCal3.GetSDev()<<endl;

		}
	}

}
void CGlobalOperator::OnSnapShot()
{	
	char strName[MAX_PATH];
	sprintf_s<MAX_PATH>(strName,"result\\snapshort%u.log",GetCurTime()/1000);
	ofstream fout(strName);
	if(fout)
	{
		vector<CNode*> cOnlineNodeList;
		g_pScheduler->GetOnlineNode(cOnlineNodeList);
		for(unsigned i = 0;i<cOnlineNodeList.size();i++)
		{
			CMKadNode* p = (CMKadNode*) cOnlineNodeList[i];
			fout<<p->m_cId.ToString().c_str()<<endl;
			fout<<p->m_nRadius<<endl;
			fout<<p->m_cLocalData.size()<<endl;
		}
	}
};
int CGlobalOperator::FindKeyGlobal(const KEY & cDest, const int nMaxDis)
{
	int nRealRes = 0;
	for(int n = 0;n<m_nDataPublishCount;n++)
	{
		if(KEY::GetDistance(cDest,m_cDataImage[n])<=nMaxDis)
		{
			nRealRes++;
		}
	}
	return nRealRes;

}
